/* 
 * This code is part of the smartlink project, see
 * 
 * 		http://code.google.com/p/smartlink/.
 * 
 * Copyright (C) 2008 Oliver Noelle
 * 
 * SmartLink is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * SmartLink is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with SmartLink.  If not, see <http://www.gnu.org/licenses/>.
 **/
package org.smartlink.search;

/**
 * a searchstring is represented as a number of ngrams, organised by this class
 * a representation of a searchstring as an efficient ngram-datastructure this
 * representation needs to be build only once per searchstring
 */
class NgramRep {
	public int minNgramLen, maxNgramLen, noLevels;
	/** number ngrams representing the searchstring */
	public int noNgrams;
	public int[] noNgramsInLevel = new int[FuzzySearch.MAXIMUM_NGRAM_LENGTH];
	public int[] lenNgramsInLevel = new int[FuzzySearch.MAXIMUM_NGRAM_LENGTH];
	/** score of all ngrams added up = maximum score an entry can get */
	int maxScore;
	/** pointer to an array of ngrams */
	public NgramEntry[] ngrams;

	/** Divides searchstring into ngrams and build data structure */
	public NgramRep(String searchStr, int minNgramLen, int maxNgramLen) {
		int length = searchStr.length();
		this.minNgramLen = minNgramLen;
		this.maxNgramLen = maxNgramLen;
		noLevels = maxNgramLen - minNgramLen + 1;

		int i, j;
		noNgrams = 0;
		for (i = minNgramLen, j = 0; i <= maxNgramLen; i++, j++) {
			noNgrams += Math.max(length - i + 1, 0);
			noNgramsInLevel[j] = Math.max(length - i + 1, 0);
			lenNgramsInLevel[j] = i;
		}

		ngrams = new NgramEntry[noNgrams + 1];

		// divide searchstring into ngrams
		NgramEntry pre1, pre2;
		int total = 1; // keep in ngs[0] a pseudo ngram with found always
		// =true
		ngrams[0] = new NgramEntry("", null, null);
		maxScore = 0;

		// for each level (=length of ngrams) get all ngrams
		for (int level = 0; level < noLevels; level++) {
			for (i = 0; i < noNgramsInLevel[level]; i++) {
				if (level != 0) {
					pre1 = ngrams[total - noNgramsInLevel[level] - 1];
					pre2 = ngrams[total - noNgramsInLevel[level]];
				} else {
					pre1 = null;
					pre2 = null;
				}
				ngrams[total] = new NgramEntry(searchStr.substring(i, i + lenNgramsInLevel[level]), pre1, pre2);
				maxScore += ngrams[total].entropy;
				total++;
			}
		}
	}

	public String toString() {
		String out = "";
		int total = 0;
		for (int level = 0; level < noLevels; level++) {
			for (int i = 0; i < noNgramsInLevel[level]; i++) {
				NgramEntry entry = ngrams[total];
				out += total + " ngram: '" + entry + "'\n";
				total++;
			}
		}
		return out;
	}

};
